local ExcelMap = require("excel.Map")
local Timer = require("core.Timer")
local Map = require("core.Map")
local Msg = require("core.Msg")
local Obj = require("core.Obj")
local ObjHuman = require("core.ObjHuman")
local ObjMonster = require("core.ObjMonster")
local ExcelPet = require("excel.Pet")
local ExcelSkill = require("excel.Skill")
local BufferNotify = require("buffer.Notify")
local RoleDefine = require("role.RoleDefine")
local SkillConditions = require("skill.Conditions")
local Status = require("scene.Status")
local CombatCalc = require("skill.CombatCalc")
local PetAi = require("pet.PetAi")
local PetLogic = require("pet.PetLogic")
local Utility = require("excel.Skill").Utility
local Buffer = require("buffer.Buffer")

function callPet(human)
	local fight_pet = human.fight_pet_id and Obj.getObj(human.fight_pet_id, human.fight_pet_uid)
	local map_id = Map.scene_id_to_map_id[human.scene_id]
	if fight_pet then
		if ExcelMap.scene[map_id].can_use_pet == 0 or fight_pet.db.hp == 0 then
--		  PetLogic.statusChange(human, fight_pet.db.id)	  
			destroy(fight_pet)
		elseif fight_pet.scene_id ~= human.scene_id then
			Obj.leaveScene(fight_pet)
			local randomNum = math.random(1,22)
			Obj.enterScene(fight_pet, human.scene_id, human.x+ randomNum, human.y - randomNum)
		end
	else
		if ExcelMap.scene[map_id].can_use_pet == 1 and human.db.petCombatId ~= 0 then
					local pet = create(human, human.db.petCombatId)
					if human.petSkillInfo and human.petSkillInfo[pet.db.id] then
					  pet.skillUserData = human.petSkillInfo[pet.db.id] 
					end
					Obj.enterScene(pet, human.scene_id, human.x - 50, human.y)					
					if pet.db.hp == 0 then
            pet.is_hide = true
            PetAi.send_hide(pet)
          end
		end
	end
end

function update(human)
  local fight_pet = human.fight_pet_id and Obj.getObj(human.fight_pet_id, human.fight_pet_uid)
  if fight_pet then
    Obj.sendArea(getObjAdd(fight_pet), fight_pet.scene_id, fight_pet.x, fight_pet.y)
  end
end

function daiji(human)
  local fight_pet = human.fight_pet_id and Obj.getObj(human.fight_pet_id, human.fight_pet_uid)
  if fight_pet then
    if fight_pet.skillUserData then
      if not human.petSkillInfo then
        human.petSkillInfo = {}
      end
      human.petSkillInfo[fight_pet.db.id] = fight_pet.skillUserData
    end
    destroy(fight_pet)
  end
end

function reset(human)
  local fight_pet = human.fight_pet_id and Obj.getObj(human.fight_pet_id, human.fight_pet_uid)
  if fight_pet then
    PetLogic.initAttr(human, fight_pet)
    doCalc(fight_pet)
    setHp(fight_pet, fight_pet.db.hp or 0x7fffffff)
  end
end

function backPet(human)
  local fight_pet = human.fight_pet_id and Obj.getObj(human.fight_pet_id, human.fight_pet_uid)
  if not fight_pet then
      return
  end
  local owner = Obj.getOwner(fight_pet)
  if owner then
    owner.db.petCombatId = 0
  end
  destroy(fight_pet)
  human.fight_pet_id = nil
  human.fight_pet_uid = nil  
end

function create(human, id)
	local t = Obj.getObj(human.fight_pet_id, human.fight_pet_uid)
	if t then
		assert()
	end
	local pet = {}
	Obj.create(pet, Obj.TYPE_PET)
	pet.camps = human.camps
	pet.dir = 4
	pet.owner = {id = human.id, uid = human.uid, attr_from_self = true, uuid = human._id}
	human.fight_pet_id = pet.id
	human.fight_pet_uid = pet.uid
	pet.owner_name = human.name
	pet.owner_uuid = human._id
	pet.db = ObjHuman.getPet(human, id)
	if not pet.db then
		assert()
	end
	pet.lv = human.db.lv
	pet.bufAttr = {}
	pet.attr = {}
	pet.buf = {}
	pet.bufLen = 0
	pet.radius	= ExcelPet.pet[pet.db.id].radius
	pet.event_time = {}
	CombatCalc.initAttr(pet)
	PetLogic.initAttr(human, pet)
  pet.speed = human.speed-- + 16
	doCalc(pet)
	setHp(pet, pet.db.hp)
	return pet
end

function destroy(pet)
	Buffer.destroy(pet)
	Obj.destroy(pet)
end

function doCalc(pet)
	Buffer.calcsInit(pet)
  for k in pairs(pet.attr) do
      pet.attr[k] = 0
  end
  local human = Obj.getOwner(pet)
  if not human or not human.db then
    return
  end
  pet.attr[RoleDefine.SPEED_RATE] = 0
  pet.attr[RoleDefine.ATK_RATE] = 0
  pet.attr[RoleDefine.DEF_RATE] = 0
  pet.attr[RoleDefine.HP_MAX_RATE] = 0
  PetLogic.initAttr(human, pet)
  pet.attr[RoleDefine.SPEED] = pet.speed
	Buffer.refreshRate(pet)
	Buffer.refresh(pet)
	CombatCalc.calcAttr(pet)	
  Obj.setSpeed(pet, pet.attr[RoleDefine.SPEED])
  pet.attr[RoleDefine.SPEED] = pet.attr[RoleDefine.SPEED] * (1 + pet.attr[RoleDefine.SPEED_RATE])
  pet.attr[RoleDefine.ATK] = pet.attr[RoleDefine.ATK] * (1 + pet.attr[RoleDefine.ATK_RATE])
  pet.attr[RoleDefine.DEF] = pet.attr[RoleDefine.DEF] * (1 + pet.attr[RoleDefine.DEF_RATE])
  pet.attr[RoleDefine.HP_MAX] = pet.attr[RoleDefine.HP_MAX] * (1 + pet.attr[RoleDefine.HP_MAX_RATE])  
end

function getBuf(pet)
	return pet.buf,pet.bufLen
end
function setBufLen(pet, len)
  pet.bufLen = len
end
function getAttr(pet, key)
	return pet.attr[key] or 0
end

function getBodyInfo(pet, id)
  local cf
  if id then
    cf = ExcelPet.pet[id]
  else
    cf = ExcelPet.pet[pet.db.id]
  end
	return  cf.source,cf.weapon[1],0,cf.pifengId,cf.horse,0,cf.weapon[2],0
end

function getHp(pet)
	return pet.db.hp
end

function getHpMax(pet)  
	return pet.attr[RoleDefine.HP_MAX]
end

function getLv(pet)
	return pet.lv
end

function getObjAdd(pet)
	local cf = ExcelPet.pet[pet.db.id]
	local mm = Msg.gc.GC_ADD_PET
	mm.obj_id = pet.id
	mm.name = cf.petMingzi 
	mm.x = pet.x
	mm.y = pet.y
	mm.speed = pet.speed
	mm.dir = pet.dir or 0
	mm.points[0] = pet.path_len * 2
	for i = 1, pet.path_len do
		local j = pet.path_len + 1 - i
		mm.points[2 * i - 1] = pet.path[2 * j - 1]
		mm.points[2 * i] = pet.path[2 * j]
	end
	mm.owner_name = pet.owner_name or ""
	mm.owner_uuid = pet.owner_uuid or ""
	mm.hp = pet.db.hp
	mm.hp_max = getHpMax(pet)
	mm.lv = pet.db.lv
	mm.is_hide = pet.is_hide and 1 or 0
	if pet.db.hp <= 0 then
	 mm.is_hide = 1
	end	
	mm.stageLv = pet.db.stage
	mm.body_h = ExcelPet.pet[pet.db.id].body_h
	mm.scale = ExcelPet.pet[pet.db.id].scale
	mm.star = pet.db.star
	BufferNotify.setBufferInfo(pet, mm.bufInfo)	
	Status.makeViewInfo(mm.viewInfo, 0, Obj.getBodyInfo(pet))

	return mm
end

function getName(pet)
	return ExcelPet.pet[pet.db.id].name
end

function getRadius(pet)
	return pet.radius
end

function onDie(pet, attacker, utilityConfig, hurt_mul)
	Obj.stop(pet)
	pet.db.next_create_time = Timer.now + ExcelPet.pet[pet.db.id].revive_cd
	local mm = Msg.gc.GC_PET_REVIVE_SEC
	mm.sec = (pet.db.next_create_time - Timer.now) / 1000
	local human = Obj.getOwner(pet)
	if human then
		Msg.send(mm, human.fd)
		PetAi.data.pet = pet
  	PetAi.data.owner = human
		PetAi.action.rand_talk("die")
	end
	pet.attacker_id = nil
  pet.attacker_uid = nil
	Obj.sendGCObjDie(pet, attacker, utilityConfig, hurt_mul)
	pet.is_hide  = true
end

function onBeHit(attacker,pet)
	if not pet.attacker_id and (not attacker.monster_id or ObjMonster.getValueByMonsterType(attacker, "can_select") == 1) and SkillConditions.isEnemy(pet, attacker) then
		pet.attacker_id = attacker.id
		pet.attacker_uid = attacker.uid
	end
end
local tb = {"mainUtility", "mustUtility", "appendUtility1", "appendUtility2", "appendUtility3"}
function onSkill(pet, x, y,skillID)
	local config = ExcelSkill.Skill[skillID]
	if config.actionID[1]~=-1 then
		if Timer.last_exe_time.walk and Timer.now - Timer.last_exe_time.walk > 200 then
			Obj.stop(pet)
		else
			Obj.resetPathParam(pet)
		end
	end
	local qianyao_time = config.qianyao_sec>0 and config.qianyao_sec*1000 or config.actionDelay
  if not pet.wake_up_time or pet.wake_up_time < qianyao_time + Timer.now then
        pet.wake_up_time = qianyao_time + Timer.now
  end
  for _, v in ipairs(tb) do
        local cf = Utility[config[v]]
        if cf and (cf.utility == "rush" or cf.utility == "jumpTo") then
            pet.wake_up_time = 1000 + Timer.now
            break
        end
  end
end


function setHp(pet, hp)	
	hp = math.max(0, hp)
	hp = math.min(hp, getHpMax(pet))
	hp = math.floor(hp)
--	if hp == pet.db.hp then
--		return
--	end
	pet.db.hp = hp
	local human = Obj.getOwner(pet)
	
	if human then
		local mm = Msg.gc.GC_PET_HEAD_HP
		mm.hp = hp
		mm.hp_max = getHpMax(pet)
		Msg.send(mm, human.fd)
	end
end

